Embodiments of the inventive subject matter generally relate to the field of managing locks in a data processing system and more specifically to software object lock management using observations
In a multi-threaded managed runtime, such as a Java™ Virtual Machine, applications and middleware such as IBM® WebSphere® Application Server are typically permitted to synchronize, or lock an object. Locking an object allows multiple threads to safely operate on objects by guaranteeing atomicity. In Java this is done using the ‘synchronized’ keyword. The locking technique can be applied to particular methods (synchronized methods) or blocks of code within methods (synchronized blocks). The runtime must be able to lock objects efficiently to achieve maximum performance. Typically, each object has a word reserved in the object header which is used to implement locking (the lock word). While the reserved word allows for efficient locking, allocating space for the lock word can be wasteful. In real-world applications, typically a small fraction of objects actually participate in locking. Therefore the lock word remains unused while contributing to an increased object footprint and reduced cache efficiency.
A technique to reduce object header sizes, referred to as a lock-nursery, requires identification of objects which are used in multi-threaded lock operations. Objects which are identified as requiring locking are given a special lock word in the object body, while other objects have no lock word. The technique saves a word in objects which are identified as non-locking. Since locking objects are typically a small subset of the object population the memory savings can be substantial.
However there is a significant penalty for misidentifying an object as non-locking. Instead of using an easily located lock word in the object body, the runtime system must refer to a side table to find a lock for the object. A simple heuristic has been proposed to identify locking objects. Any object which is an instance of a class that includes synchronized methods is considered to be a locking object. All other objects are considered to be non-locking. While suitable for benchmarks, real world experience has shown that this heuristic is insufficient for certain applications. Some classes which use locks extensively may have no synchronized methods. When these characteristics are important in a specific application, performance may suffer an unacceptable degradation.
A proposed solution involves detecting when the heuristic fails at runtime. When a sufficient number of locking operations are performed on non-locking objects, the runtime system could quiesce all threads and then “grow” the objects in question, giving them a lock slot. However growing an object at runtime can be a very expensive and time consuming operation. Growing a software object would require patching all just in time compiled code which allocates such objects to reflect the new object size. Resizing may not be possible at all when the system is low on memory, because the resized objects consume more memory and possibly more memory than is available.